/*
 * $Id$
 * $HeadURL$
 *
 * ==============================================================================
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.jettyrunner.server;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

/**
 * @author Andrei Solntsev
 * @version $Revision: $ $Date: $ $Author: $
 */
public class IOUtils
{
	// Constants
	public static final String HTTP_HEADER_CONTENT_TYPE = "Content-Type";
	public static final String CONTENT_TYPE_HTML = "text/html";
	public static final String HTTP_METHOD_POST = "POST";
	public static final String HTTP_METHOD_GET = "GET";

	protected static final String CLASS_VERSION = "$Revision: 1.2 $ $Author: asolntsev $";

	public static final void closeSilently(OutputStream out)
	{
		if (out != null)
		{
			try
			{
				out.close();
			}
			catch (IOException ioe)
			{
				// keep silence
			}
		}
	}

	public static final void closeSilently(InputStream in)
	{
		if (in != null)
		{
			try
			{
				in.close();
			}
			catch (IOException ioe)
			{
				// keep silence
			}
		}
	}

	public static final void closeSilently(Reader in)
	{
		if (in != null)
		{
			try
			{
				in.close();
			}
			catch (IOException ioe)
			{
				// keep silence
			}
		}
	}

	public static final void closeSilently(Writer out)
	{
		if (out != null)
		{
			try
			{
				out.close();
			}
			catch (IOException ioe)
			{
				// keep silence
			}
		}
	}

	public static String removeDuplicatedSlashes(String str)
	{
		if (str == null)
			return str;

		return str.replaceAll("(?<=[^:])/{2,}", "/");
	}

	public static String postHtml(String sUrl, String sContent) throws IOException
	{
		return post(sUrl, CONTENT_TYPE_HTML, sContent);
	}

	public static String post(String sUrl, String sContentType, String sContent) throws IOException
	{
		URL url = new URL(sUrl);
		return post(url, sContentType, sContent);
	}

	public static String postHtml(URL url, String sContent) throws IOException
	{
		return post(url, CONTENT_TYPE_HTML, sContent);
	}

	public static String post(URL url, String sContentType, String sContent) throws IOException
	{
		HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
		try
		{
			httpConnection.setRequestMethod(HTTP_METHOD_POST);
			httpConnection.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, sContentType);
			httpConnection.setDoOutput(true);

			printText(httpConnection.getOutputStream(), sContent);
			return readText(httpConnection);
		}
		finally
		{
			httpConnection.disconnect();
		}
	}

	public static byte[] postHtmlReturningBytes(URL url, String sContent) throws IOException
	{
		return postReturningBytes(url, CONTENT_TYPE_HTML, sContent);
	}

	public static byte[] postReturningBytes(URL url, String sContentType, String sContent) throws IOException
	{
		HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
		try
		{
			httpConnection.setRequestMethod(HTTP_METHOD_POST);
			httpConnection.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, sContentType);
			httpConnection.setDoOutput(true);

			printText(httpConnection.getOutputStream(), sContent);
			return readBytes(httpConnection);
		}
		finally
		{
			httpConnection.disconnect();
		}
	}

	public static void printText(OutputStream out, String sContent)
	{
		PrintWriter pwOut = new PrintWriter(out);
		try
		{
			pwOut.write(sContent);
			pwOut.flush();
		}
		finally
		{
			pwOut.close();
		}
	}

	public static HttpResponse readHttpContent(String url) throws IOException
	{
		return readHttpContent( new URL(url));
	}

	public static String readText(String url) throws IOException
	{
		return readText( new URL(url));
	}

	public static HttpResponse readHttpContent(URL url) throws IOException
	{
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		HttpResponse response = new HttpResponse();
		response.returnCode = conn.getResponseCode();
		response.content = readText( conn );
		return response;
	}

	public static String readText(URL url) throws IOException
	{
		return readText( (HttpURLConnection) url.openConnection() );
	}

	public static String readText(HttpURLConnection httpConnection) throws IOException
	{
		return readText( httpConnection.getInputStream() );
	}

	public static String readText(File f) throws IOException
	{
		// Read the result
		return readText( new FileReader(f) );
	}

	public static String readText(InputStream in) throws IOException
	{
		// Read the result
		return readText( new InputStreamReader(in) );
	}

	public static String readText(Reader rIn) throws IOException
	{
		try
		{
			StringBuffer szbReturn = new StringBuffer();
			char[] caBuffer = new char[10*1024];	// 10 kb buffer

			while (true)
			{
				int nRead = rIn.read(caBuffer);

				if (nRead < 0)
					break;

				szbReturn.append(caBuffer, 0, nRead);
			}

			return szbReturn.toString();
		}
		finally
		{
			closeSilently( rIn );
		}
	}

	public static byte[] readBytes(HttpURLConnection httpConnection) throws IOException
	{
		// Get the length of resulting content
		int nContentLength = httpConnection.getContentLength();
		int bufferSize = (nContentLength > 0) ? nContentLength : 1024;

		InputStream inputStream = httpConnection.getInputStream();
		try
		{
			return readBytes( inputStream, bufferSize );
		}
		finally
		{
			// Close the HTTP connection
			closeSilently( inputStream );
		}
	}

	public static byte[] readBytes(InputStream in) throws IOException
	{
		return readBytes(in, 512);
	}

	public static byte[] readBytes(InputStream in, int initialSize) throws IOException
	{
		ByteArrayOutputStream out = new ByteArrayOutputStream(initialSize);
		writeBytes(in, out);
		return out.toByteArray();
	}

	public static boolean writeBytes(InputStream in, OutputStream out) throws IOException
	{
		boolean isEmptyFile = true;

		try
		{
			byte[] inputBuffer = new byte[1024];

			int bytesRead;
			while ((bytesRead = in.read(inputBuffer)) != -1)
			{
				out.write(inputBuffer, 0, bytesRead);
				isEmptyFile = false;
			}
		}
		finally
		{
			closeSilently( in );
			closeSilently( out );
		}

		return isEmptyFile;
	}
}
